#ifndef __ENDIAN_H
#define __ENDIAN_H

#define __BYTE_ORDER_LITTLE 0xDCBA
#define __BYTE_ORDER_BIG 0xABCD
#define __BYTE_ORDER_PDP 0xBADC       /* DEC PDP-11 (aka __BYTE_ORDER_LITTLE_WORD) */
#define __BYTE_ORDER_HONEYWELL 0xCDAB /* Honeywell 316 (aka __BYTE_ORDER_BIG_WORD) */
#define __BYTE_ORDER_LITTLE_WORD    __BYTE_ORDER_PDP
#define __BYTE_ORDER_BIG_WORD       __BYTE_ORDER_HONEYWELL



#if ((defined __C51__) || (defined __RC51__) || (defined _CC51))

#define __BYTE_ORDER_HOST __BYTE_ORDER_BIG

#elif ((defined SDCC) || (defined HI_TECH_C) || (defined __ICC8051__))

#define __BYTE_ORDER_HOST __BYTE_ORDER_LITTLE

#elif defined(__CC_ARM) // ARMCC
#if defined(__BIG_ENDIAN)
#define __BYTE_ORDER_HOST __BYTE_ORDER_BIG
#else
#define __BYTE_ORDER_HOST __BYTE_ORDER_LITTLE
#endif
#define bswap32(x) __rev(x)     // ARMCC builtin function
#define bswap16(x) (__rev(x)>>16)
#elif defined(__GNUC__) // GNU

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define __BYTE_ORDER_HOST __BYTE_ORDER_LITTLE
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define __BYTE_ORDER_HOST __BYTE_ORDER_BIG
#endif


#define bswap16(x) __builtin_bswap16(x)
#define bswap32(x) __builtin_bswap32(x)
#define bswap64(x) __builtin_bswap64(x)

#elif defined(_MSC_VER) // MSVC
#define __BYTE_ORDER_HOST __BYTE_ORDER_LITTLE
#else
#error unknow compiler
#endif // Compiler Definitions

/* bit swap */
#ifndef bswap16
#define bswap16(x) ((x & 0x00ff) << 8 | (x & 0xff00) >> 8)
#endif // !bswap16

#ifndef bswap32
#define bswap32(x) (((x)&0x000000ff) << 24 | ((x)&0x0000ff00) << 8 | ((x)&0x00ff0000) >> 8 | ((x)&0xff000000) >> 24)
#endif // !bswap16

#ifndef bswap64
#define bswap64(x) (((x) >> 56) | (((x)&0x00ff000000000000) >> 40) | (((x)&0x0000ff0000000000) >> 24) | (((x)&0x000000ff00000000) >> 8) | (((x)&0x00000000ff000000) << 8) | (((x)&0x0000000000ff0000) << 24) | (((x)&0x000000000000ff00) << 40) | (((x) << 56)))
#endif // !bswap64
/* word swap */
#define wswap32(x) (((x)&0x0000ffff) << 16 | ((x)&0xffff0000) >> 16)

#if (__BYTE_ORDER_HOST == __BYTE_ORDER_BIG )
#define cpu_to_be16(x) (x)
#define cpu_to_be32(x) (x)
#define cpu_to_le16(x) bswap16((uint16_t)(x))
#define cpu_to_le32(x) bswap32((uint32_t)(x))

#define be16_to_cpu(x) (x)
#define be32_to_cpu(x) (x)
#define le16_to_cpu(x) bswap16((uint16_t)(x))
#define le32_to_cpu(x) bswap32((uint32_t)(x))

#elif (__BYTE_ORDER_HOST == __BYTE_ORDER_LITTLE)
#define cpu_to_be16(x) bswap16((uint16_t)(x))
#define cpu_to_be32(x) bswap32((uint32_t)(x))
#define cpu_to_le16(x) (x)
#define cpu_to_le32(x) (x)

#define be16_to_cpu(x) bswap16((uint16_t)(x))
#define be32_to_cpu(x) bswap32((uint32_t)(x))
#define le16_to_cpu(x) (x)
#define le32_to_cpu(x) (x)
#elif (__BYTE_ORDER_HOST == __BYTE_ORDER_PDP)
#elif (__BYTE_ORDER_HOST == __BYTE_ORDER_HONEYWELL)
#else
#error Unknow Byte Order
#endif // 0


#define htobe16(x) cpu_to_be16((x))
#define htobe32(x) cpu_to_be32((x))
#define htole16(x) cpu_to_le16((x))
#define htole32(x) cpu_to_le32((x))

#define be16toh(x) be16_to_cpu((x))
#define be32toh(x) be32_to_cpu((x))
#define le16toh(x) le16_to_cpu((x))
#define le32toh(x) le32_to_cpu((x))

#endif // __ENDIAN_H
